package com.example.iot;

import androidx.annotation.Nullable;

import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.Description;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.LimitLine;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;

import java.util.ArrayList;
import java.util.List;

public class LineChartManager {
    private final LineChart lineChart;
    private List<Entry> entryList;
    private int sampleMaxCount;
    private final YAxis leftAxis;
    private final YAxis rightAxis;
    private final XAxis xAxis;
    private LineData lineData;
    private LineDataSet lineDataSet;

    public LineChartManager(LineChart mLineChart, String name, int color) {
        lineChart = mLineChart;
        sampleMaxCount = 10;
        leftAxis = lineChart.getAxisLeft();
        rightAxis = lineChart.getAxisRight();
        xAxis = lineChart.getXAxis();
        initLineChart();
        initLineDataSet(name, color);
    }

    private void initLineChart() {
        lineChart.setDrawGridBackground(false);
        lineChart.setDrawBorders(true);

        Legend legend = lineChart.getLegend();
        legend.setForm(Legend.LegendForm.LINE);
        legend.setTextSize(11f);
        legend.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM);
        legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT);
        legend.setOrientation(Legend.LegendOrientation.HORIZONTAL);
        legend.setDrawInside(false);

        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxis.setGranularity(1f);
        xAxis.setLabelCount(10);

        leftAxis.setAxisMinimum(0f);
        rightAxis.setAxisMinimum(0f);
    }

    private void initLineDataSet(String name, int color) {
        lineDataSet = new LineDataSet(null, name);
        lineDataSet.setLineWidth(1.5f);
        lineDataSet.setCircleRadius(1.5f);
        lineDataSet.setColor(color);
        lineDataSet.setCircleColor(color);
        lineDataSet.setHighLightColor(color);
        lineDataSet.setDrawFilled(true);
        lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT);
        lineDataSet.setValueTextSize(10f);
        lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);

        lineData = new LineData();
        lineChart.setData(lineData);
    }

    public void addEntry(float number) {
        if (entryList == null) {
            entryList = new ArrayList<>();
            for (int i = 0; i < sampleMaxCount; i++) {
                entryList.add(new Entry(entryList.size(), 0));
            }
        }
        if (entryList.size() >= sampleMaxCount) {
            entryList.remove(0);

            for (int i = 0; i < entryList.size(); i++) {
                Entry entry = entryList.get(i);
                entry.setX(entry.getX() - 1);
                entryList.set(i, entry);
            }
        } else {
            int size = entryList.size();
            for (int i = 0; i < sampleMaxCount - size - 1; i++) {
                entryList.add(new Entry(entryList.size(), 0));
            }
        }

        entryList.add(new Entry(entryList.size(), number));
        lineDataSet.setEntries(entryList);
        lineDataSet.setDrawValues(false);

        if (lineData.getDataSetCount() == 0) {
            lineData.addDataSet(lineDataSet);
        }

        lineChart.setData(lineData);
        lineChart.notifyDataSetChanged();
        lineChart.invalidate();
    }

    public void clear() {
        entryList.clear();
        lineDataSet.setEntries(entryList);
        lineDataSet.setDrawValues(false);

        if (lineData.getDataSetCount() == 0) {
            lineData.addDataSet(lineDataSet);
        }

        lineChart.setData(lineData);
        lineData.notifyDataChanged();
        lineChart.notifyDataSetChanged();
        lineChart.invalidate();
    }

    public void setSampleMaxCount(int maxCount) {
        sampleMaxCount = maxCount;
    }

    public void setYAxis(float max, float min, int labelCount) {
        if (max < min) {
            return;
        }
        leftAxis.setAxisMaximum(max);
        leftAxis.setAxisMinimum(min);
        leftAxis.setLabelCount(labelCount, true);

        rightAxis.setAxisMaximum(max);
        rightAxis.setAxisMinimum(min);
        rightAxis.setLabelCount(labelCount, true);

        lineChart.invalidate();
    }

    public void setHighLimitLine(float high, int color, @Nullable String name) {
        if (name == null) {
            name = "";
        }
        LimitLine highLimitLine = new LimitLine(high, name);
        highLimitLine.setLineWidth(4f);
        highLimitLine.setTextSize(10f);
        highLimitLine.setLineColor(color);
        highLimitLine.setTextColor(color);
        leftAxis.addLimitLine(highLimitLine);

        lineChart.invalidate();
    }

    public void setLowLimitLine(float low, int color, @Nullable String name) {
        if (name == null) {
            name = "";
        }
        LimitLine lowLimitLine = new LimitLine(low, name);
        lowLimitLine.setLineWidth(4f);
        lowLimitLine.setTextSize(10f);
        lowLimitLine.setLineColor(color);
        lowLimitLine.setTextColor(color);
        leftAxis.addLimitLine(lowLimitLine);

        lineChart.invalidate();
    }

    public void setDescription(String str) {
        Description description = new Description();
        description.setText(str);
        lineChart.setDescription(description);

        lineChart.invalidate();
    }

    public LineChart getLineChart() {
        return lineChart;
    }

    public int getSampleMaxCount() {
        return sampleMaxCount;
    }

    public YAxis getLeftAxis() {
        return leftAxis;
    }

    public YAxis getRightAxis() {
        return rightAxis;
    }

    public XAxis getxAxis() {
        return xAxis;
    }

    public LineData getLineData() {
        return lineData;
    }

    public LineDataSet getLineDataSet() {
        return lineDataSet;
    }
}
